package com.uziot.javassist.test2;

import com.uziot.javassist.test1.JavassistTest2;
import javassist.*;
import org.springframework.util.ReflectionUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;

/**
 * @author shidt
 * @version V1.0
 * @className JavassistTest2
 * @date 2022-06-06 22:47:00
 * @description
 */

public class JavassistTest21 {

    public static void main(String[] args) throws CannotCompileException, IOException {

        URL resource = JavassistTest2.class.getClassLoader().getResource("");
        String file = resource.getFile();
        System.out.println("文件存储路径：" + file);

        ClassPool cp = ClassPool.getDefault();
        CtClass ctClass = cp.makeClass("com.uziot.javassist.Hello2");

        //添加一个hello1的方法
        CtMethod ctMethod = new CtMethod(CtClass.voidType, "hello2", new CtClass[]{CtClass.intType, CtClass.doubleType}, ctClass);
        ctMethod.setModifiers(Modifier.PUBLIC);
        ctClass.addMethod(ctMethod);

        //添加一个int类型的，名字为value的变量
        CtField ctField = new CtField(CtClass.intType, "value", ctClass);
        ctField.setModifiers(Modifier.PRIVATE);
        ctClass.addField(ctField);

        //为value变量添加set方法
        CtMethod setValue = new CtMethod(CtClass.voidType, "setValue", new CtClass[]{CtClass.intType}, ctClass);
        setValue.setModifiers(Modifier.PUBLIC);
        //设置方法体
        setValue.setBody("this.value = $1;");

        ctClass.addMethod(setValue);

        //为value变量添加get方法
        CtMethod getValue = new CtMethod(CtClass.intType, "getValue", new CtClass[]{}, ctClass);
        getValue.setModifiers(Modifier.PUBLIC);

        //设置方法体
        getValue.setBody("{ System.out.println(this.value); return this.value; } ");
        ctClass.addMethod(getValue);

        ctClass.writeFile(file);
        // 生成class类
        //Class<?> clazz = ctClass.toClass();
        //创建对象
        try {
            Class<?> clazz = Class.forName("com.uziot.javassist.Hello2");
            Object obj = clazz.newInstance();
            Field field = ReflectionUtils.findField(clazz, "value");
            if (null != field) {
                ReflectionUtils.setField(field, obj, 13899);
                Method method = ReflectionUtils.findMethod(clazz, "getValue");
                if (method != null) {
                    ReflectionUtils.invokeMethod(method, obj);
                }
            }
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
}
